<html>
<!--
  The MIT License (MIT)

  Copyright (c) 2007-2013 Einar Lielmanis and contributors.

  Permission is hereby granted, free of charge, to any person
  obtaining a copy of this software and associated documentation files
  (the "Software"), to deal in the Software without restriction,
  including without limitation the rights to use, copy, modify, merge,
  publish, distribute, sublicense, and/or sell copies of the Software,
  and to permit persons to whom the Software is furnished to do so,
  subject to the following conditions:

  The above copyright notice and this permission notice shall be
  included in all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.
  -->

<head>
    <meta charset="utf-8">
    <title>Online JavaScript beautifier</title>
    <link rel="icon" href="web/favicon.png" type="image/png">
    <link rel="stylesheet" href="web/third-party/codemirror/lib/codemirror.css">

    <script src="web/third-party/codemirror/lib/codemirror.js"></script>
    <script src="web/third-party/codemirror/mode/javascript/javascript.js"></script>

    <style>
        body {
            background: #eee;
            color: #333;
        }
        img {
            border: 0;
        }
        a.self {
            font-weight: bold;
            text-decoration: none;
            color: #444;
            border-bottom: 1px solid #aaa
        }
        p, select, label, .blurb, a.turn-off-codemirror {
            font:13px/1.231 arial, sans-serif;
            *font-size:small;
        }
        a.turn-off-codemirror {
            margin-left: 25px;
        }
        button.submit {
            width: 100%;
            padding: 10px 0;
            cursor: pointer;
            margin: 0;
        }
        button.submit em {
            font-size: 11px;
            font-style: normal;
            color: #999;
        }
        label {
            cursor: pointer;
        }
        select {
            width: 220px;
        }
        table#options {
            float: right;
        }
        table#options td {
            vertical-align: top;
            padding-left: 10px;
        }
        #about {
            float: left;
        }
        #about p {
            margin: 0 6px 6px 0;
        }
        li {
            line-height: 150%;
        }
        li.writeme {
            padding-top: 8px;
        }
        #testresults {
            display: none;
            font-family: monaco, "lucida console", "courier new", monospace;
        }
        .CodeMirror {
            border: 1px solid #ccc;
            height: 450px;
            font-size: 90%;
            margin-bottom: 6px;
            background: white;
        }
        p {
            margin-left: 40px;
            margin-right: 40px;
        }
        a {
            white-space: nowrap;
            color: #36d;
        }
        .contributor-sep {
            border-top: 1px solid #ccc;
            padding-top: 8px;
        }
    </style>
    <script src="web/third-party/jquery/jquery.js"></script>
    <script src="web/third-party/jquery/jquery.cookie.js"></script>


    <script src="js/lib/beautify.js"></script>
    <script src="js/lib/beautify-css.js"></script>
    <script src="js/lib/beautify-html.js"></script>
    <script src="js/test/sanitytest.js"></script>
    <script src="js/test/beautify-tests.js"></script>
    <script src="js/lib/unpackers/javascriptobfuscator_unpacker.js"></script>
    <script src="js/lib/unpackers/urlencode_unpacker.js"></script>
    <script src="js/lib/unpackers/p_a_c_k_e_r_unpacker.js"></script>
    <script src="js/lib/unpackers/myobfuscate_unpacker.js"></script>

    <script>
        var the = {
            use_codemirror: (!window.location.href.match(/without-codemirror/)),
            beautify_in_progress: false,
            editor: null // codemirror editor
        };

        function run_tests() {
            var st = new SanityTest();
            run_beautifier_tests(st, Urlencoded, js_beautify);
            JavascriptObfuscator.run_tests(st);
            P_A_C_K_E_R.run_tests(st);
            Urlencoded.run_tests(st);
            MyObfuscate.run_tests(st);
            var results = st.results_raw().replace(/ /g, '&nbsp;').replace(/\r/g, '·').replace(/\n/g, '<br>');
            $('#testresults').html(results).show();
        }


        function any(a, b) {
            return a || b;
        }

        function read_settings_from_cookie() {
            $('#tabsize').val(any($.cookie('tabsize'), '4'));
            $('#brace-style').val(any($.cookie('brace-style'), 'collapse'));
            $('#detect-packers').prop('checked', $.cookie('detect-packers') !== 'off');
            $('#max-preserve-newlines').val(any($.cookie('max-preserve-newlines'), '5'));
            $('#keep-array-indentation').prop('checked', $.cookie('keep-array-indentation') === 'on');
            $('#break-chained-methods').prop('checked', $.cookie('break-chained-methods') === 'on');
            $('#indent-scripts').val(any($.cookie('indent-scripts'), 'normal'));
            $('#space-before-conditional').prop('checked', $.cookie('space-before-conditional') !== 'off');
            $('#wrap-line-length').val(any($.cookie('wrap-line-length'), '0'));
            $('#unescape-strings').prop('checked', $.cookie('unescape-strings') === 'on');
        }

        function store_settings_to_cookie() {
            var opts = {
                expires: 360
            };
            $.cookie('tabsize', $('#tabsize').val(), opts);
            $.cookie('brace-style', $('#brace-style').val(), opts);
            $.cookie('detect-packers', $('#detect-packers').prop('checked') ? 'on' : 'off', opts);
            $.cookie('max-preserve-newlines', $('#max-preserve-newlines').val(), opts);
            $.cookie('keep-array-indentation', $('#keep-array-indentation').prop('checked') ? 'on' : 'off', opts);
            $.cookie('break-chained-methods', $('#break-chained-methods').prop('checked') ? 'on' : 'off', opts);
            $.cookie('space-before-conditional', $('#space-before-conditional').prop('checked') ? 'on' : 'off',
                opts);
            $.cookie('unescape-strings', $('#unescape-strings').prop('checked') ? 'on' : 'off', opts);
            $.cookie('wrap-line-length', $('#wrap-line-length').val(), opts);
            $.cookie('indent-scripts', $('#indent-scripts').val(), opts);
        }

        function unpacker_filter(source) {
            var trailing_comments = '',
                comment = '',
                unpacked = '',
                found = false;

            // cut trailing comments
            do {
                found = false;
                if (/^\s*\/\*/.test(source)) {
                    found = true;
                    comment = source.substr(0, source.indexOf('*/') + 2);
                    source = source.substr(comment.length).replace(/^\s+/, '');
                    trailing_comments += comment + "\n";
                } else if (/^\s*\/\//.test(source)) {
                    found = true;
                    comment = source.match(/^\s*\/\/.*/)[0];
                    source = source.substr(comment.length).replace(/^\s+/, '');
                    trailing_comments += comment + "\n";
                }
            } while (found);

            var unpackers = [P_A_C_K_E_R, Urlencoded, /*JavascriptObfuscator,*/ MyObfuscate];
            for (var i = 0; i < unpackers.length; i++) {
                if (unpackers[i].detect(source)) {
                    unpacked = unpackers[i].unpack(source);
                    if (unpacked != source) {
                        source = unpacker_filter(unpacked);
                    }
                }
            }

            return trailing_comments + source;
        }


        function beautify() {
            if (the.beautify_in_progress) return;

            store_settings_to_cookie();

            the.beautify_in_progress = true;

            var source = the.editor ? the.editor.getValue() : $('#source').val(),
                output,
                opts = {};

            opts.indent_size = $('#tabsize').val();
            opts.indent_char = opts.indent_size == 1 ? '\t' : ' ';
            opts.max_preserve_newlines = $('#max-preserve-newlines').val();
            opts.preserve_newlines = opts.max_preserve_newlines !== -1;
            opts.keep_array_indentation = $('#keep-array-indentation').prop('checked');
            opts.break_chained_methods = $('#break-chained-methods').prop('checked');
            opts.indent_scripts = $('#indent-scripts').val();
            opts.brace_style = $('#brace-style').val();
            opts.space_before_conditional = $('#space-before-conditional').prop('checked');
            opts.unescape_strings = $('#unescape-strings').prop('checked');
            opts.wrap_line_length = $('#wrap-line-length').val();
            opts.space_after_anon_function = true;

            if (looks_like_html(source)) {
                output = html_beautify(source, opts);
            } else {
                if ($('#detect-packers').prop('checked')) {
                    source = unpacker_filter(source);
                }
                output = js_beautify(source, opts);
            }
            if (the.editor) {
                the.editor.setValue(output);
            } else {
                $('#source').val(output);
            }

            the.beautify_in_progress = false;
        }

        function looks_like_html(source) {
            // <foo> - looks like html
            // <!--\nalert('foo!');\n--> - doesn't look like html

            var trimmed = source.replace(/^[ \t\n\r]+/, '');
            var comment_mark = '<' + '!-' + '-';
            return (trimmed && (trimmed.substring(0, 1) === '<' && trimmed.substring(0, 4) !== comment_mark));
        }
    </script>
</head>

<body>

    <div id="about">
        <p>
            <a class="self" href="./">Beautify, unpack or deobfuscate JavaScript and HTML, make JSON/JSONP readable, etc.</a>
        </p>
        <p>
            All of the source code is completely free and open, available on the <a href="https://github.com/einars/js-beautify">github</a> under MIT licence,
            <br>and we have a command-line version, python library and a <a href="https://npmjs.org/package/js-beautify">node package</a> as well.
        </p>
    </div>


    <table id="options">
        <tr>
            <td>
                <select name="tabsize" id="tabsize">
                    <option value="1">Indent with a tab character</option>
                    <option value="2">Indent with 2 spaces</option>
                    <option value="3">Indent with 3 spaces</option>
                    <option value="4">Indent with 4 spaces</option>
                    <option value="8">Indent with 8 spaces</option>
                </select>
                <br>

                <select name="max-preserve-newlines" id="max-preserve-newlines">
                    <option value="-1">Remove all extra newlines</option>
                    <option value="1">Allow 1 newline between tokens</option>
                    <option value="2">Allow 2 newlines between tokens</option>
                    <option value="5">Allow 5 newlines between tokens</option>
                    <option value="10">Allow 10 newlines between tokens</option>
                    <option value="0">Allow unlimited newlines between tokens</option>
                </select>
                <br>

                <select name="wrap-line-length" id="wrap-line-length">
                    <option value="0">Do not wrap lines</option>
                    <option value="40">Wrap lines near 40 characters</option>
                    <option value="70">Wrap lines near 70 characters</option>
                    <option value="80">Wrap lines near 80 characters</option>
                    <option value="110">Wrap lines near 110 characters</option>
                    <option value="120">Wrap lines near 120 characters</option>
                    <option value="160">Wrap lines near 160 characters</option>
                </select>
                <br>

                <select id="brace-style">
                    <option value="collapse">Braces with control statement</option>
                    <option value="expand">Braces on own line</option>
                    <option value="end-expand">End braces on own line</option>
                </select>

                <p style="margin:6px 0 0 0">HTML &lt;style&gt;, &lt;script&gt; formatting:</p>
                <select id="indent-scripts">
                    <option value="keep">Keep indent level of the tag</option>
                    <option value="normal">Add one indent level</option>
                    <option value="separate">Separate indentation</option>
                </select>

            </td>
            <td>

                <input class="checkbox" type="checkbox" id="detect-packers">
                <label for="detect-packers">Detect packers and obfuscators?</label>
                <br>
                <input class="checkbox" type="checkbox" id="keep-array-indentation">
                <label for="keep-array-indentation">Keep array indentation?</label>
                <br>
                <input class="checkbox" type="checkbox" id="break-chained-methods">
                <label for="break-chained-methods">Break lines on chained methods?</label>
                <br>
                <input class="checkbox" type="checkbox" id="space-before-conditional">
                <label for="space-before-conditional">Space before conditional: "if(x)" / "if (x)"</label>
                <br>
                <input class="checkbox" type="checkbox" id="unescape-strings">
                <label for="unescape-strings">Unescape printable chars encoded as \xNN or \uNNNN?</label>
                <br><a href="?without-codemirror" class="turn-off-codemirror">Use a simple textarea for code input?</a>


            </td>
        </tr>
    </table>

    <div style="line-height: 0">
        <button class="submit"><strong>Beautify JavaScript or HTML</strong>  <em>(ctrl-enter)</em>
        </button>
        <textarea id="source" rows="30" cols="160"></textarea>
        <button class="submit"><strong>Beautify JavaScript or HTML</strong>  <em>(ctrl-enter)</em>
        </button>
    </div>

    <div class="blurb">
        <div style="float:right; width: 210px;">
            <a style="display:block; float: left; padding-top: 3px" href="http://flattr.com/thing/94550/jsbeautifier-org" target="_blank">
                <img src="http://api.flattr.com/button/flattr-badge-large.png" alt="Flattr">
            </a>
            <form action="https://www.paypal.com/cgi-bin/webscr" method="post">
                <input type="hidden" name="cmd" value="_s-xclick">
                <input type="hidden" name="hosted_button_id" value="TL28UJK2ARCUJ">
                <input style="border:0" type="image" src="web/paypal-donate.gif" name="submit" alt="PayPal - The safer, easier way to pay online!">
                <img alt="" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
            </form>
        </div>

        <p>Browser extensions and other uses:</p>
        <ul id="uses">

            <li>A <a href="javascript:(function(){s=document.getElementsByTagName('SCRIPT');tx='';sr=[];for(i=0;i<s.length;i++){with(s.item(i)){t=text;if(t){tx+=t;}else{sr.push(src)};}};with(window.open()){document.write('<textarea id=&quot;t&quot;>'+(sr.join(&quot;\n&quot;))+&quot;\n\n-----\n\n&quot;+tx+'</textarea><script src=&quot;http://jsbeautifier.org/beautify.js&quot;></script><script>with(document.getElementById(&quot;t&quot;)){value=js_beautify(value);with(style){width=&quot;99%&quot;;height=&quot;99%&quot;;borderStyle=&quot;none&quot;;}};</script>');document.close();}})();"><strong>bookmarklet</strong></a> (drag
                it to your bookmarks) by Ichiro Hiroshi to see all scripts used on the page,</li>

            <li style="margin-top: 8px"><strong>Chrome</strong>: <a href="https://github.com/rixth/jsbeautify-for-chrome">jsbeautify-for-chrome</a> by Tom Rix,</li>
            <li><strong>Chrome</strong>: <a href="https://chrome.google.com/webstore/detail/piekbefgpgdecckjcpffhnacjflfoddg">Pretty Beautiful JavaScript</a> by Will McSweeney,
            </li>
            <li><strong>Chrome</strong>: <a href="https://chrome.google.com/webstore/detail/cfmcghennfbpmhemnnfjhkdmnbidpanb">Quick source viewer</a> by Tomi Mickelsson
                (
                <a href="https://github.com/tomimick/chrome-ext-view-src">github</a>, <a href="http://tomicloud.com/2012/07/viewsrc-chrome-ext">blog</a>),</li>
            <li style="margin-top: 8px"><strong>Firefox</strong>: <a href="https://addons.mozilla.org/en-US/firefox/addon/javascript-deminifier/">Javascript deminifier</a> by Ben Murphy, to be
                used together with the firebug (<a href="https://github.com/benmmurphy/jsdeminifier_xpi/">github</a>),</li>
            <li style="margin-top: 8px"><strong>Safari</strong>: <a href="http://spadin.github.com/js-beautify-safari-extension">Safari extension</a> by Sandro Padin,</li>
            <li style="margin-top: 8px"><strong>Opera</strong>: <a href="https://addons.opera.com/addons/extensions/details/readable-javascript/">Readable JavaScript</a> (
                <a href="https://github.com/Dither/readable-javascript">github</a>) by Dither,</li>
            <li><strong>Opera</strong>: <a href="https://addons.opera.com/addons/extensions/details/source/">Source</a> extension by Deathamns,</li>
            <li style="margin-top: 8px"><strong>Sublime Text 2:</strong>  <a href="https://github.com/jdc0589/JsFormat">JsFormat</a>, a javascript formatting plugin for this nice editor by Davis
                Clark,</li>
            <li style="margin-top: 8px"><strong>vim:</strong>  <a href="https://github.com/michalliu/sourcebeautify.vim">sourcebeautify.vim</a>, a plugin by michalliu (requires node.js, V8, SpiderMonkey
                or cscript js engine),</li>
            <li><strong>vim:</strong>  <a href="https://github.com/maksimr/vim-jsbeautify">vim-jsbeautify</a>, a plugin by Maksim Ryzhikov (node.js or V8 required),</li>
            <li style="margin-top: 12px"><a href="http://fiddler2.com/">Fiddler</a> proxy: <a href="http://fiddler2.com/Fiddler2/extensions.asp">JavaScript Formatter addon</a>,
                <li><a href="https://github.com/nagaozen/gedit-tunnings/">gEdit tips</a> by Fabio Nagao,</li>
                <li><a href="http://akelpad.sourceforge.net/forum/viewtopic.php?p=11246#11246">Akelpad extension</a> by Infocatcher,</li>
                <li>Beautifier in <a href="http://sethmason.com/2011/04/28/jsbeautify-in-emacs.html">Emacs</a> write-up by Seth Mason,</li>
                <li><a href="http://c9.io">Cloud9</a>, a lovely IDE running in a browser, working in the node/cloud, uses jsbeautifier (<a href="https://github.com/ajaxorg/cloud9">github</a>),</li>
                <li><a href="http://www.symetronapps.com/pages/apps/shrinker.html">Shrinker</a>, a non-free JavaScript packer for Mac. I&nbsp;haven't used it, so I&nbsp;have
                    no idea if it's any good,</li>
                <li><a href="http://www.restconsole.com/">REST Console</a>, a request debugging tool for Chrome, beautifies JSON responses (<a href="https://github.com/codeinchaos/rest-console">github</a>),</li>
                <li><a href="http://mitmproxy.org/">mitmproxy</a>, a nifty SSL-capable HTTP proxy, provides pretty javascript responses (<a href="https://github.com/cortesi/mitmproxy">github</a>).</li>
                <li><a href="http://www.wakanda.org/">wakanda</a>, a neat IDE for web and mobile applications has a <a href="http://forum.wakanda.org/showthread.php?1483-3-new-extensions-JSLint-Beautifier-and-Snippet">Beautifier extension</a> (
                    <a href="https://github.com/Wakanda/wakanda-extensions/tree/master/Beautifier">github</a>).</li>
                <li><a href="http://portswigger.net/burp/">Burp Suite</a> now has a <a href="http://code.google.com/p/burp-suite-beautifier-extension/">beautfier extension</a>,
                    thanks to Soroush Dalili,</li>
                <li><a href="http://plugins.netbeans.org/plugin/43263/jsbeautify">Netbeans jsbeautify</a> plugin by Drew Hamlett (
                    <a href="https://github.com/drewhjava/netbeans-jsbeautify">github</a>).</li>
                <li><a href="https://github.com/drewhjava/brackets-beautify">brackets-beautify-extension</a> for <a href="http://brackets.io">Adobe Brackets</a> by Drew
                    Hamlett (<a href="https://github.com/drewhjava/brackets-beautify">github</a>),</li>
                <li><a href="http://codecaddy.net/">codecaddy.net</a>, a collection of webdev-related tools, assembled by Darik Hall,
                <li><a href="http://www.editey.com/">www.editey.com</a>, an interesting and free Google-Drive oriented editor uses this beautifier.
                <li class="writeme">Doing anything interesting? Write me to einar@jsbeautifier.org and I'll include your link.</li>
        </ul>

        <p class="contributors contributor-sep">Written by Einar Lielmanis, <a href="mailto:einar@jsbeautifier.org">einar@jsbeautifier.org</a>, maintained and evolved by <a href="https://github.com/bitwiseman/">Liam Newman</a>.</p>
        <p class="contributors">We use the wonderful <a href="http://codemirror.net">CodeMirror</a> syntax highlighting editor, written by Marijn Haverbeke.
        </p>
        <p class="contributors">Made with a great help of Jason&nbsp;Diamond, Patrick&nbsp;Hof, Nochum&nbsp;Sossonko, Andreas&nbsp;Schneider,
            <br>Dave&nbsp;Vasilevsky,
            <a href="http://my.opera.com/Vital/blog/">Vital&nbsp;Batmanov</a>, Ron&nbsp;Baldwin, Gabriel&nbsp;Harrison,
            <a href="http://shullian.com">Chris J. Shull</a>,
            <a href="http://mathiasbynens.be/">Mathias Bynens</a>,
            <br>
            <a href="https://www.vittgam.net/">Vittorio Gambaletta</a>,
            <a href="https://github.com/esseks">Stefano Sanfilippo</a> and
            <a href="https://github.com/evocateur">Daniel Stockman</a>.
        </p>

        <p style="text-align:right">
            <a href="#" style="color: #ccc; border-bottom: 1px dashed #ccc; text-decoration: none;" onclick="run_tests(); return false;">Run the tests</a>
        </p>

    </div>
    <div id="testresults"></div>
    <script>
        $(function () {

            read_settings_from_cookie();

            var default_text =
                "// This is just a sample script. Paste your real code (javascript or HTML) here.\n\nif ('this_is'==/an_example/){of_beautifer();}else{var a=b?(c%d):e[f];}";
            var textArea = $('#source')[0];

            if (the.use_codemirror && typeof CodeMirror !== 'undefined') {
                the.editor = CodeMirror.fromTextArea(textArea, {
                        theme: 'default',
                        lineNumbers: true
                    });
                the.editor.focus();

                the.editor.setValue(default_text);
                $('.CodeMirror').click(function () {
                    if (the.editor.getValue() == default_text) {
                        the.editor.setValue('');
                    }
                });
            } else {
                $('#source').val(default_text).bind('click focus', function () {
                    if ($(this).val() == default_text) {
                        $(this).val('');
                    }
                }).bind('blur', function () {
                    if (!$(this).val()) {
                        $(this).val(default_text);
                    }
                });
            }


            $(window).bind('keydown', function (e) {
                if (e.ctrlKey && e.keyCode == 13) {
                    beautify();
                }
            })
            $('.submit').click(beautify);
            $('select').change(beautify);


        });
    </script>
    <script>
        var _gaq = [
            ['_setAccount', 'UA-7409939-1'],
            ['_trackPageview']
        ];
        (function (d, t) {
            var g = d.createElement(t),
                s = d.getElementsByTagName(t)[0];
            g.src = '//www.google-analytics.com/ga.js';
            s.parentNode.insertBefore(g, s);
        }(document, 'script'));
    </script>
</body>

</html>
